<?php

class EASYNC_entity_generator_connection {
    
    public function get($host, $user, $password, $database) {
        return $this->conn($host, $user, $password, $database) . $this->dbm() . $this->dbm_orm();
    }
    
    
    protected function conn($host, $user, $password, $database) {
        $s = "
            class model_conn {

    protected static \$conn = NULL;

    public static \$host = '$host';
    public static \$usuario = '$user';
    public static \$senha = '$password';
    public static \$banco = '$database';


    /**
     *
     * @return model_dbm_orm
     */
    public static function get_conn() {
        if (self::\$conn === NULL) {
            self::\$conn = new model_dbm_orm(array(
                self::\$host,
                self::\$usuario,
                self::\$senha, 
                self::\$banco
            ));
            self::\$conn->usarUtf8();
        }
        return self::\$conn;
    }
}
";
        
        return $s;
    }
    
    protected function dbm_orm() {
        $s = "class model_dbm_orm extends model_dbm {

    public function q(\$string_query = NULL) {
        return \$this->query(\$string_query);
    }
    
    public function getDatabaseInfo() {
        \$provisorio = array();
        \$tabelas = array();

        \$r = \$this->qcv(\"SHOW TABLES\", \"*\");

        foreach (\$r as \$v) {
            foreach (\$v as \$v2) {
                array_push(\$provisorio, \$v2);
            }
        }
        
        foreach (\$provisorio as \$v) {
            array_push(\$tabelas, array(\$v => \$this->getColumnNames(\$v)));
        }
        return \$tabelas;
    }

    protected function getColumnNames(\$tabela) {
        
        \$columns = array();
        
        \$this->q(\"SELECT * FROM \$tabela LIMIT 1\");

        \$i = 0;
        while (\$i < mysql_num_fields(\$this->query)) {
            \$meta = mysql_fetch_field(\$this->query, \$i);
            
            \$columns[\$meta->name] = array(\$meta->primary_key, \$meta->not_null);
            \$i++;
        }
        mysql_free_result(\$this->query);
        return \$columns;
    }

}";
        return $s;
    }
    
    protected function dbm() {
        $s = "

class model_dbm {
    
    public static \$qtde_consultas = 0;
    
    protected \$host;
    protected \$user;
    protected \$password;
    protected \$db;

    protected \$rows = '*';
    protected \$row;
    protected \$query;
    protected \$regex_pattern;
    protected \$fetch_assoc_ja_executado_para_nova_query = false;
    protected \$vet_provisorio;
    protected \$resp_multiple_rows;
    protected \$resp_single_row;
    protected \$columns_names_type;
    protected \$usar_limite = false;
    protected \$string_query;
    protected \$select_all_columns = false;
    protected \$fetch_row = false;
    protected \$resource = NULL;
    protected \$prefixo_todas_tabelas = NULL;
    protected \$logar_acoes = false;
    protected \$usuario_logar_acoes = NULL;
    protected \$tipo_acoes_logar = array('UPDATE', 'DELETE');

    public function __construct(\$vet_conexao = NULL) {
        //echo 'nova instância Dbm; ';
        if (\$vet_conexao != NULL) {
            \$this->connect(\$vet_conexao);
        }
    }

    public function connect(\$vet_conexao = NULL) {
        \$this->host = \$vet_conexao[0];
        \$this->user = \$vet_conexao[1];
        \$this->password = \$vet_conexao[2];
        \$this->db = \$vet_conexao[3];
        
        if (!\$this->resource = @mysql_connect(\$this->host, \$this->user, \$this->password, TRUE)) {
            throw new DBException(\"Erro mysql_connect(): [\" . mysql_errno() . \"] \" . mysql_error());
        }
        //var_dump(\$this->conexao);
        if (!\$banco = @mysql_select_db(\$this->db, \$this->resource)) {
            throw new DBException(\"Erro mysql_select_db(): \" . mysql_error());
        }
    }

    public function logarAcoes(\$logar, \$usuario) {
        \$this->usuario_logar_acoes = \$usuario;
        \$this->logar_acoes = \$logar;
    }

    /**
     *
     * qcv - Query Columns Values
     * @return \$this->cv();
     *
     */
    public function qcv(\$string_query, \$columns_names) {
        \$this->q(\$string_query);
        return \$this->cv(\$columns_names);
    }

    // alias para query():
    public function q(\$string_query = NULL) {
        return \$this->query(\$string_query);
    }
    

    public function query(\$string_query = NULL) {
        //echo \"BANCO: \" . \$this->db . \" -- \$string_query <br>\";
        self::\$qtde_consultas++;
        
        \$this->string_query = \$string_query;
        \$this->logarAcao();
        
        if (\$this->rows == '1' && \$this->usar_limite == true) {
            // tirando o ; do fim da string e adicionando o limite:
            \$this->string_query = ereg_replace('(;)\$', '', rtrim(\$this->string_query));
            \$this->string_query.= \" LIMIT 0, 1;\";
        }
        if (!\$this->query = @mysql_query(\$this->string_query, \$this->resource)) {
            
            
            
            if(mysql_errno() == 1451) {
                throw new DBM_ForeignKeyConstraintException();
            }
            
            if(mysql_errno() == 1062) {
                throw new DBM_DuplicateKeyException();
            }
            
            // outro tipo de erro:
            throw new DBException(\"Erro mysql_query(): \" . mysql_error() . \", consulta: '\" . \$this->string_query . \"';\");
            
        }
        \$this->fetch_assoc_ja_executado_para_nova_query = false;
    }
    
    
    protected function logarAcao() {
        if (\$this->logar_acoes) {
            if (ereg(\"^(UPDATE|DELETE|INSERT)\", \$string_query)) {
                \$this->q(\"insert INTO log_atividades (id, id_usuario, atividade, dt)
				VALUES (NULL, \" . \$this->usuario_logar_acoes . \", '\" . addslashes(\$this->string_query) . \"', NOW());\");
            }
        }
    }

    public function usarUtf8() {
        // ainda não possui funcionalidade para voltar ao charset de conexão default.
        \$sql = \"SET CHARACTER SET utf8;\";
        if (!mysql_query(\$sql)) {
            throw new DBException(\"Erro ao mudar o Character Set. \" . mysql_error() . \" sql: \" . \$sql);
        }
    }

    public function useSqlLimit(\$use) {
        // true ou false
        \$this->usar_limite = \$use;
    }

    public function reloadLastQuery() {
        // chamar esta função sempre que precisar refazer a última consulta efetuada com 'query()', e posteriormente carregar os resultados com 'getColumnsValues()';
        \$this->query(\$this->string_query);
    }

    public function showQuery() {
        return \$this->string_query;
    }

    public function setRows(\$rows) {
        // '1' para apenas uma linha de retorno, e '*' para várias linhas de retorno.
        if (!ereg('^(1|\*)\$', \$rows)) {
            throw new DBException(\"Função '\" . __FUNCTION__ . \"' só aceita como valores com o seguinte padrão: ^(1|\*)\$, valor recebido: '\" . \$rows . \"';\");
        }
        \$this->rows = \$rows;
        \$this->fetch_assoc_ja_executado_para_nova_query = false;
    }

    // alias para getColumnsValues():
    public function cv(\$columns_names, \$fetch_row = false) {
        return \$this->getColumnsValues(\$columns_names, \$fetch_row);
    }

    public function getColumnsValues(\$columns_names, \$fetch_row = false) {
        // \$fetch_row = mysql_ fetch_row() (colunas como índice numérico no vetor);
        \$this->fetch_row = \$fetch_row;

        // esta função não aceita colunas que possuem vírgula no nome, pois a vírgula é usada para separar os nomes de colunas.
        if (is_string(\$columns_names)) {
            if (!preg_match('/^([^, ]+(,[^, ]+)*|\*)\$/', \$columns_names)) {
                throw new DBException(\"Separe as colunas entre vírgulas sem espaço, ou use '*', exemplos: 'cola,colb,colc', '*', 'coluna'; valor recebido: '\" . \$columns_names . \"';\");
            }
            \$colunas = explode(',', \$columns_names);
            if (sizeof(\$colunas) == 1) {
                \$this->columns_names = \$colunas[0];
            } else {
                \$this->columns_names = \$colunas;
            }
        }
        //var_dump(\$this->columns_names);
        /*
          \$columnsNames = string ou array.
          obrigatoriamente usar string caso seja apenas uma coluna;
          obrigatoriamente usar array caso sejam 2 ou mais colunas;
         */
        if (is_string(\$this->columns_names)) {
            \$this->columns_names_type = 'string';
            \$this->verificaNome('column', \$this->columns_names);
        } else if (is_array(\$this->columns_names)) {
            \$this->columns_names_type = 'array';
            foreach (\$this->columns_names as \$v) {
                
                    \$this->verificaNome('column', \$v);
                
            }
        } else {
            //echo \"nenhum tipo\";
        }
        //echo \"columns_names_type = \" . \$this->columns_names_type;
        if (\$this->columns_names == '*') {
            // selecionar todas as colunas.
            \$this->select_all_columns = true;
        } else {
            \$this->select_all_columns = false;
        }

        // a condição abaixo é útil, pois várias consultas com as mesmas variáveis 'query' e 'rows' sempre retornam o mesmo resultado na função 'getColumnsValues()', a não ser que 'reloadQuery()' seja executado, e posteriormente 'getColumnsValues()';
        if (!\$this->fetch_assoc_ja_executado_para_nova_query) {

            if (\$this->rows == '1') {
                \$this->fetchAssocSingleRow();
                return \$this->resp_single_row;
            } else if (\$this->rows == '*') {
                \$this->fetchAssocMultipleRows();
                return \$this->resp_multiple_rows;
            }
        } else {
            if (\$this->rows == '1') {
                return \$this->resp_single_row;
            } else if (\$this->rows == '*') {
                return \$this->resp_multiple_rows;
            }
        }
    }

    public function getQueryRows() {
        return mysql_num_rows(\$this->query);
    }

    protected function fetchAssocSingleRow() {
        if (\$this->getQueryRows() == 0) {
            \$this->resp_single_row = NULL;
            return;
        }

        \$this->row = \$this->fetch(\$this->query);

        if (\$this->select_all_columns) {
            \$this->resp_single_row = array();
            foreach (\$this->row as \$k => \$v) {
                \$this->resp_single_row[\$k] = \$v;
            }
        } else if (\$this->columns_names_type == 'string') {
            \$this->resp_single_row = \$this->row[\$this->columns_names];
        } else {
            // array
            \$this->resp_single_row = array();
            foreach (\$this->columns_names as \$v) {
                array_push(\$this->resp_single_row, \$this->row[\$v]);
                //array_push(\$this->resp_single_row, \$v);
                //echo \$this->row[\$v];
            }
        }
        \$this->fetch_assoc_ja_executado_para_nova_query = true;
    }

    protected function fetchAssocMultipleRows() {
        if (\$this->getQueryRows() == 0) {
            \$this->resp_multiple_rows = NULL;
            return;
        }
        \$provisoria = NULL;
        \$this->resp_multiple_rows = array();
        //echo \$this->showQuery();
        //var_dump(\$this->resp_multiple_rows);
        while (\$this->row = \$this->fetch(\$this->query)) {
            //var_dump(\$this->row);

            if (\$this->select_all_columns) {
                \$provisoria = array();
                foreach (\$this->row as \$k => \$v) {
                    \$this->provisoria[\$k] = \$v;
                }
                array_push(\$this->resp_multiple_rows, \$this->provisoria);
            } else if (\$this->columns_names_type == 'array') {
                \$provisoria = array();
                for (\$i = 0; \$i < sizeof(\$this->columns_names); \$i++) {
                    array_push(\$provisoria, \$this->row[\$this->columns_names[\$i]]);
                }
                array_push(\$this->resp_multiple_rows, \$provisoria);
            } else {
                // string
                //echo \$this->columns_names;
                array_push(\$this->resp_multiple_rows, \$this->row[\$this->columns_names]);
            }
        }
        \$this->fetch_assoc_ja_executado_para_nova_query = true;
    }

    protected function fetch(\$query) {
        if (\$this->fetch_row) {
            //echo \"fetch_row: \" . \$query . \";\";
            return mysql_fetch_row(\$this->query);
        } else {
            //echo \"fetch_assoc: \" . \$query . \";\";
            return mysql_fetch_assoc(\$this->query);
        }
    }

    public function fetchRow(\$bool) {
        \$this->fetch_row = \$bool;
    }

    protected function verificaNome(\$tipo, \$nome) {
        //echo \$tipo . \$nome;
        switch (\$tipo) {
            case 'db':
            case 'table':
                \$this->regex_pattern = '/^[^/\.]+\$/';
                break;
            case 'column':
                \$this->regex_pattern = '/^.+\$/';
                break;
            default:
                return false;
        }
        if (!preg_match(\$this->regex_pattern, \$nome))
            throw new DBException(\"nome do BD, tabela ou coluna está incorreto. parâmetros: tipo = '\" . \$tipo . \"', nome = '\" . \$nome . \"';\");
    }

    public function closeConnection() {
        mysql_close(\$this->resource);
    }

    public function lastInsertID() {
        return mysql_insert_id(\$this->resource);
    }

    public function setPefixoTodasTabelas(\$prefixo) {
        \$this->prefixo_todas_tabelas = \$prefixo;
    }
}




/* EXCEÇÕES */


/**
 * não pode remover ou adicionar registro 
 * porque é chave estrangeira em outra tabela: 
 */
class DBM_ForeignKeyConstraintException extends DBM_Exception { }


/**
 * chave duplicada (Primary key ou Unique Key):
 */
class DBM_DuplicateKeyException extends DBM_Exception { }


/**
 * Erro geral de conexão ou consulta, lançado pelo MySQL:
 */
class DBM_Exception extends Exception { }

";
        
        return $s;
    }
    
}

?>
